/*
* Copyright (c) 2011 Connection Road.  All rights reserved.
* This program and the accompanying material are made available
* under the terms of the Eclipse Public Licnese v1.0 which is
* available at http://www.eclipse.org/legal/epl-v10.html
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using CrSyncFilesForms.Properties;
using CrSyncFilesForms.Utils;
using CrSyncFilesUtils;
using CrSyncFilesUtils.Enums;

namespace CrSyncFilesForms {

    
    public partial class CrSyncUiFolderPairWizard : Form {

        
        
        public CrSyncUiFolderPairWizard() {
            InitializeComponent();
            InitializeTabControlWizard();
            FolderPair = FileSyncPairManager.CreateFolderPair();
            OptionSynchronize.Checked = true;

            AcceptButton = ButtonGoToStep2;
            CancelButton = ButtonCancelStep1;

            ComboBoxCloudContainers.Visible = false;

            ButtonBrowseSource.Click += CallBackBrowseSource;
            ButtonBrowseDestination.Click += CallBackBrowseDestination;
            Closed += CallBackClosed;
            TextBoxDestination.GotFocus += CallBackTextBoxDestinationGotFocus;

            InitializeExtension();
        }

        public void InitializeTabControlWizard(){
            var rect = new RectangleF(TabPageFolderPair.Left,
                                              TabPageFolderPair.Top,
                                              TabPageFolderPair.Width,
                                              TabPageFolderPair.Height);
            var defaultExplanation = Resources.SYNC_INFO_SYNCHRONIZE;
            LabelShortExplanation.Text = defaultExplanation;

            TabControlWizard.Region = new Region(rect);
            ButtonBackDefault.Enabled = false;
            ButtonGoToStep2.Enabled = false;
            Text = Resources.TEXT_CREATE_PAIR_STEP_1;

            
        }

        // Provides a way to initialize other class implementation
        // without attaching them on to this class.
        partial void OnLoadExtension();
        partial void InitializeExtension();
        partial void OnClosedExtension();


        //------------------------- PROPERTIES -------------------------------------

        public Boolean Create {
            get;
            set;
        }

        public DirectoryInfo SourceFolder {
            get; 
            set;
        }

        public DirectoryInfo DestinationFolder {
            get;
            set;
        }

        public FileSyncPairInfo FolderPair
        {
            get;
            set;
        }

        public String CloudStorageName { get; set; }
        private const string _defaultCloudStorageName = @"My Storage";
     
        //------------------------- HELPER METHODS --------------------------------

        /// <summary>
        /// Check if the source directory ( left folder )  is a valid file path format
        /// and that it exist. If not, spawn a dialog informing the user why it is invalid.
        /// </summary>
        /// <returns></returns>
        public bool ValidateSourceDirectory()
        {
            var currentSource = TextBoxSource.Text.Trim();
            var validator = new DirectoryValidator(currentSource);
            var result = validator.Validate();

            // Checks if source path exists and is a valid file path format
            switch (result)
            {
                case DirectoryValidatorResult.Exists:
                    return true;
                case DirectoryValidatorResult.DoesNotExists:
                    {
                        var errorMessage = String.Format(Resources.MESSAGE_DIRECTORY_DOES_NOT_EXISTS, currentSource);
                        MessageBox.Show(this, errorMessage, Resources.TEXT_TITLE_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        TextBoxSource.Focus();
                    }
                    return false;
                case DirectoryValidatorResult.InvalidPath:
                    {
                        var errorMessage = Resources.MESSAGE_DIRECTORY_PATH;
                        MessageBox.Show(this, errorMessage, Resources.TEXT_TITLE_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        TextBoxSource.Focus();
                    }
                    return false;
                default:
                    return false;
            }
        }

        /// <summary>
        /// Checks if the destination directory ( right folder )  is a valid file path format
        /// and that it exists.  If not, spawn a dialog informing the user why it is invalid.
        /// </summary>
        /// <returns></returns>
        public bool ValidateDestinationDirectory()
        {
            var currentDestination = TextBoxDestination.Text.Trim();
            var validator = new DirectoryValidator(currentDestination);
            var result = validator.Validate();

            // Check if destination path exists and is a valid file path format
            switch (result)
            {
                case DirectoryValidatorResult.Exists:
                    return true;
                case DirectoryValidatorResult.DoesNotExists:
                    {
                        var errorMessage = String.Format(Resources.MESSAGE_DIRECTORY_DOES_NOT_EXISTS, currentDestination);
                        MessageBox.Show(this, errorMessage, Resources.TEXT_TITLE_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    return false;
                case DirectoryValidatorResult.InvalidPath:
                    {
                        var errorMessage = Resources.MESSAGE_DIRECTORY_PATH;
                        MessageBox.Show(this, errorMessage, Resources.TEXT_TITLE_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error);

                    }
                    return false;
                default:
                    return false;
            }
        }

        //------------------------- CALLBACKS -------------------------------------

        private void CallBackCancel(object sender, EventArgs e) {
            Close();
        }

        private void CallBackBrowseSource(object sender, EventArgs e) {

            var dialogResult =  DialogSourceBrowser.ShowDialog(this);
            if(dialogResult == DialogResult.OK)
            {
                TextBoxSource.Text = DialogSourceBrowser.SelectedPath;
            }
        }

        private void CallBackBrowseDestination(object sender, EventArgs e) {
           if(ValidateSourceDirectory())
           {
               var dialogResult = DialogDestinationBrowser.ShowDialog(this);
               if (dialogResult == DialogResult.OK)
               {
                   TextBoxDestination.Text = DialogDestinationBrowser.SelectedPath;
               }
           }
        }

        private void CallBackDestinationChanged(object sender, EventArgs e) {
            if ((TextBoxDestination.TextLength >= 1) && (TextBoxSource.TextLength >= 1)) {
                ButtonGoToStep2.Enabled = true;
            }else{
                ButtonGoToStep2.Enabled = false;
            }
        }

        private void CallBackGoToStep2(object sender, EventArgs e)
        {

            // Check if user wants to sync to the cloud
            if(CheckBoxCloud.Checked)
            {
                // Check if the user provided a valid source directory else there's no reason to complete the wizard.
                if(ValidateSourceDirectory())
                {
                    // Make sure that the user provides the correct cloud path format
                    
                    var regex = new Regex("[^a-zA-Z0-9]");
                    if(regex.Match(TextBoxDestination.Text).Success)
                    {
                        MessageBox.Show(this,
                                        "You entered an invalid Cloud Storage Name.  Special characters are not allowed.",
                                        "CRSyncFiles",
                                        MessageBoxButtons.OK,
                                        MessageBoxIcon.Information);
                        ComboBoxCloudContainers.Focus();
                    }
                    else if(TextBoxDestination.Text.Contains(@"\"))
                    {
                        MessageBox.Show(this,
                                        "You entered an invalid Cloud Storage Name.  Alphanumeric characters only.",
                                        "CRSyncFiles",
                                        MessageBoxButtons.OK,
                                        MessageBoxIcon.Information);
                        ComboBoxCloudContainers.Focus();
                    }
                    else if (TextBoxDestination.Text.Length >= 1)
                    {
                        Text = Resources.TEXT_CREATE_PAIR_STEP_2;

                        FolderPair.LeftFolder = FileSyncPairManager.CreateFileLocation(TextBoxSource.Text,
                                                                                       ApplicationGlobals.Prefix,
                                                                                       Guid.NewGuid().ToString(),
                                                                                       ApplicationGlobals.
                                                                                           MetaDataDirectory);

                        FolderPair.RightFolder = FileSyncPairManager.CreateFileLocation(TextBoxDestination.Text,
                                                                                        ApplicationGlobals.Prefix,
                                                                                        Guid.NewGuid().ToString(),
                                                                                        ApplicationGlobals.
                                                                                            MetaDataDirectory,
                                                                                        CrSyncFileLocationTypes.Azure); // We forcefully create location of type azure
                        TabControlWizard.SelectTab(1);

                        PanelSteps.BackgroundImage = Resources.dotStep2;

                        // Disable other sync method,  because the cloud only supports two sync
                        OptionContribute.Enabled = false;
                        OptionContribute.Hide();
                        OptionEcho.Enabled = false;
                        OptionEcho.Hide();

                        AcceptButton = ButtonGoToStep3;
                        CancelButton = ButtonCancelStep2;
                    }
                    else
                    {
                        // Else we point the user to the problem
                        MessageBox.Show(this,
                                        "You entered an invalid Cloud Storage Name.",
                                        "CRSyncFiles",
                                        MessageBoxButtons.OK,
                                        MessageBoxIcon.Information);
                        ComboBoxCloudContainers.Focus();
                    }
                    
                }
                else
                {
                    // Else point the user to the problem
                    TextBoxSource.Focus();
                }
            }
            else
            {
                // Validate the source directory first
                if(ValidateSourceDirectory())
                {
                    // Then validate the destination directory
                    if(ValidateDestinationDirectory())
                    {
                        // Make sure that the user did not provide the same source and destination or the sync would get in an endless loop
                        var sourceNode = new FileNode(TextBoxSource.Text.Trim());
                        var destinationNode = new FileNode(TextBoxDestination.Text.Trim());

                        Console.WriteLine("TEST 1 = "+sourceNode.IsChildOf(destinationNode) + " 2 = "+destinationNode.IsChildOf(sourceNode));

                        if ((sourceNode.Path != destinationNode.Path) && (!sourceNode.IsChildOf(destinationNode)) && (!destinationNode.IsChildOf(sourceNode)))
                        {
                            FolderPair.LeftFolder = FileSyncPairManager.CreateFileLocation(TextBoxSource.Text, ApplicationGlobals.Prefix, Guid.NewGuid().ToString(), ApplicationGlobals.MetaDataDirectory);
                            FolderPair.RightFolder = FileSyncPairManager.CreateFileLocation(TextBoxDestination.Text, ApplicationGlobals.Prefix, Guid.NewGuid().ToString(), ApplicationGlobals.MetaDataDirectory);

                            Text = Resources.TEXT_CREATE_PAIR_STEP_2;

                            // Move to the next step
                            TabControlWizard.SelectTab(1);
                            OptionSynchronize.Select();
                            PanelSteps.BackgroundImage = Resources.dotStep2;
                            AcceptButton = ButtonGoToStep3;
                            CancelButton = ButtonCancelStep2;

                            // Since we're not syncing to cloud, make all sync method/action types available.
                            OptionContribute.Enabled = true;
                            OptionContribute.Show();
                            OptionEcho.Enabled = true;
                            OptionEcho.Show();
                        }
                        else
                        {
                            MessageBox.Show(this, Resources.MESSAGE_RECURSIVE_FOLDER, Resources.TEXT_RECURSIVE_FOLDERS, MessageBoxButtons.OK, MessageBoxIcon.Error);
                            AcceptButton = ButtonGoToStep2;
                            CancelButton = ButtonCancelStep1;
                        }
                    }
                    else
                    {
                        // Point the user to the other problem
                        TextBoxDestination.Focus();
                    }
                }
                else
                {
                    // Else point the user to the problem
                    TextBoxSource.Focus();
                }
            }
        }

        private void CallBackGoToStep3(object sender, EventArgs e) {
            Text = Resources.TEXT_CREATE_PAIR_STEP_3;
            TabControlWizard.SelectTab(2);
            TextBoxFolderPairName.Select();
            AcceptButton = ButtonFinish;
            CancelButton = ButtonCancelStep3;
            PanelSteps.BackgroundImage = Resources.dotStep3;

        }

        private void CallBackGoToStep1(object sender, EventArgs e) {
            Text = Resources.TEXT_CREATE_PAIR_STEP_1;
            TabControlWizard.SelectTab(0);
            AcceptButton = ButtonGoToStep2;
            CancelButton = ButtonCancelStep1;
            PanelSteps.BackgroundImage = Resources.dotStep1;
        }

        private void ShowSynchronizeToolTip(object sender, EventArgs e) {
            var toolTip = new ToolTip();
            var explanation = Resources.SYNC_INFO_SYNCHRONIZE;
            toolTip.SetToolTip(OptionSynchronize,explanation);
        }

        private void ShowEchoToolTip(object sender, EventArgs e) {
            var toolTip = new ToolTip();
            var explanation = Resources.SYNC_INFO_ECHO;
            toolTip.SetToolTip(OptionEcho, explanation);
        }

        private void ShowContributeToolTip(object sender, EventArgs e) {
            var toolTip = new ToolTip();
            var explanation = Resources.SYNC_INFO_CONTRIBUTE;
            toolTip.SetToolTip(OptionContribute, explanation);
        }

        private void SelectSynchronize(object sender, EventArgs e)
        {
            var explanation = Resources.SYNC_INFO_SYNCHRONIZE;
            LabelShortExplanation.Text = explanation;
            ButtonGoToStep3.Enabled = true;
            FolderPair.FolderPairActionTypeId = (int)FolderPairActionTypeEnum.Synchronize;
            //Console.WriteLine("SYNCHRONIZE");
        }

        private void SelectEcho(object sender, EventArgs e)
        {
            var explanation = Resources.SYNC_INFO_ECHO;
            LabelShortExplanation.Text = explanation;
            ButtonGoToStep3.Enabled = true;
            FolderPair.FolderPairActionTypeId = (int)FolderPairActionTypeEnum.Echo;
            //Console.WriteLine("ECho");
        }

        private void SelectContribute(object sender, EventArgs e)
        {
            var explanation = Resources.SYNC_INFO_CONTRIBUTE;
            LabelShortExplanation.Text = explanation;
            ButtonGoToStep3.Enabled = true;
            FolderPair.FolderPairActionTypeId = (int)FolderPairActionTypeEnum.Contribute;
            //Console.WriteLine("CONTRIBUTE");
        }

        private void CallBackBackToStep2(object sender, EventArgs e)
        {
            Text = Resources.TEXT_CREATE_PAIR_STEP_2;
            TabControlWizard.SelectTab(1);
            AcceptButton = ButtonGoToStep3;
            CancelButton = ButtonCancelStep2;
            PanelSteps.BackgroundImage = Resources.dotStep2;
            Text = Resources.TEXT_CREATE_PAIR_STEP_2;
        }

        private void CallBackFolderPairNameChanged(object sender, EventArgs e)
        {
            if(TextBoxFolderPairName.Text != null){
                if (TextBoxFolderPairName.TextLength >= 1)
                {
                    if(TextBoxFolderPairName.Text.Trim().ToUpper() != "ALL FOLDER PAIRS")
                    {
                        var folderPairNameExists = ApplicationGlobals.PairManager.HasFolderPairNamed(TextBoxFolderPairName.Text.Trim());
                        ButtonFinish.Enabled = !folderPairNameExists;
                        if (folderPairNameExists)
                        {
                            LabelFolderPairNameNotes.ForeColor = Color.Red;
                        }
                        else
                        {
                            LabelFolderPairNameNotes.ForeColor = Color.Black;
                        }
                    }
                    else
                    {
                        ButtonFinish.Enabled = false;
                        LabelFolderPairNameNotes.ForeColor = Color.Red;
                    }
                }
                else
                {
                    ButtonFinish.Enabled = false;
                    LabelFolderPairNameNotes.ForeColor = Color.Black;
                }
            }
        }

        private void CallBackButtonFolderPairWizardFinished(object sender, EventArgs e)
        {
            
            var newFolderPairName = TextBoxFolderPairName.Text;
            if (Regex.Match(newFolderPairName, @"[a-zA-Z0-9].*\s*").Success) {
                FolderPair.FolderPairName = newFolderPairName;
                FolderPair.ExtendedInfo.AddObjectForKey(CheckBoxCloud.Checked, "SYNC_TO_CLOUD");
                DialogResult = DialogResult.OK;
                Close();
            }else{
                MessageBox.Show(Resources.MESSAGE_FOLDER_PAIR_NAME, Resources.TEXT_TITLE_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void TabPagePairNameClick(object sender, EventArgs e)
        {

        }

        private void CallBackLoad(object sender, EventArgs e)
        {
            // Color Scheme
            BackColor = CRSyncColors.DialogBackGround;
            TabControlWizard.BackColor = CRSyncColors.DialogBackGround;
            TabPageFolderPair.BackColor = CRSyncColors.DialogBackGround;
            TabPageMethod.BackColor = CRSyncColors.DialogBackGround;
            TabPagePairName.BackColor = CRSyncColors.DialogBackGround;
            LabelChooseFolder.ForeColor = CRSyncColors.Title;
            LabelExample.ForeColor = CRSyncColors.ForeColor;
            LabelFolderPairName.ForeColor = CRSyncColors.Title;
            LabelLeft.ForeColor = CRSyncColors.Title;
            LabelRight.ForeColor = CRSyncColors.Title;
            LabelShortExplanation.ForeColor = CRSyncColors.ForeColor;
            label3.ForeColor = CRSyncColors.ForeColor;
            GroupShortExplanation.ForeColor = CRSyncColors.ForeColor;
            OptionContribute.ForeColor = CRSyncColors.ForeColor;
            OptionEcho.ForeColor = CRSyncColors.ForeColor;
            OptionSynchronize.ForeColor = CRSyncColors.ForeColor;
            LinkLabelGetAccount.LinkColor = CRSyncColors.LinkForeColor; 
            LinkLabelHelp.LinkColor = CRSyncColors.LinkForeColor;
            LinkMoreInfo.LinkColor = CRSyncColors.LinkForeColor;
            LinkMoreInfo2.LinkColor = CRSyncColors.LinkForeColor;
            CheckBoxCloud.ForeColor = CRSyncColors.ForeColor; 

            // Max dimension
            var height = Height;
            var width = Width;
            MaximumSize = new Size(width,height);


            // Default initialization
            TextBoxSource.Select();
            CheckBoxCloud.Visible = false;
            CheckBoxCloud.Enabled = false;

            OnLoadExtension();
        }


        protected virtual void CallBackClosed(object  sender, EventArgs args)
        {
            OnClosedExtension();
        }

        private void LinkLabelHelpLinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            var helpDialog = new CrSyncUiWizardHelpDialog();
            helpDialog.ShowDialog(this);
        }

        private void LinkMoreInfoLinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start(Settings.Default.CFG_URL_ONLINE_DOC);
        }

        

        private void CallBackTextBoxDestinationGotFocus(object sender, EventArgs args)
        {
            TextBoxDestination.GotFocus -= CallBackTextBoxDestinationGotFocus;
            if(!ValidateSourceDirectory())
            {
                TextBoxSource.Focus();
            }
            TextBoxDestination.GotFocus += CallBackTextBoxDestinationGotFocus;
        }
    }
}
